//
//  InputKeyManage.swift
//  iDev
//
//  Created by lbxia on 2021/9/8.
//

import Foundation
import Cocoa
import CoreFoundation
import ApplicationServices

//包含键值 kVK_xxx  定义
import Carbon

class InputKeyManage {
    
//    static public let shared: InputKeyManage = InputKeyManage()

    
    // MARK: - 模拟键盘输入
    
    class func testKeyboardInput()  {
        
        //需要系统允许app使用辅助功能，首次会提示权限，点击打开，会跳转到 设置->安全与隐私->辅助功能
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            
            
//            NSCursor *sysCursor = [NSCursor currentSystemCursor];
//
//            if (sysCursor == nil) {
//                NSLog(@"nil");
//            }
//

            
            //当前app可以比较 iBeam 输入光标
//            if NSCursor.current == NSCursor.iBeam{
//                print("")
//            }
            
            //系统层比较无效
            if NSCursor.currentSystem == NSCursor.iBeam{
                print("")
            }
            
            //输入 a
//            self.keyboardInputKey(key: KeyVirtualKey.kVK_ANSI_A.rawValue, keyDown: true)
//            self.keyboardInputKey(key: KeyVirtualKey.kVK_ANSI_A.rawValue, keyDown: false)
////
////            //输入 s
//            self.keyboardInputKey(key: KeyVirtualKey.kVK_ANSI_S.rawValue, keyDown: true)
//            self.keyboardInputKey(key: KeyVirtualKey.kVK_ANSI_S.rawValue, keyDown: false)
            

            //一个辅助键
            //大写
//            self.keyboardCombine(virtualKey: KeyVirtualKey.kVK_ANSI_A.rawValue, combineFlag: .maskShift)
//            self.keyboardCombine(virtualKey: KeyVirtualKey.kVK_ANSI_A.rawValue, combineFlag: .maskShift, keyDown: false)
            
            
            // command +c 复制
//            self.keyboardCombine(virtualKey: 0x08, combineFlag: .maskCommand)
//            //测试不调用 up ,功能正常
//            self.keyboardCombine(virtualKey: 0x08, combineFlag: .maskCommand, keyDown: false)

            
            //多重辅助组合键
            //放大 在safari 打开网页，测试正常
//            let combineFlag = CGEventFlags(rawValue: CGEventFlags.maskAlternate.rawValue | CGEventFlags.maskCommand.rawValue)
//            self.keyboardCombine(virtualKey: CGKeyCode(KeyVirtualKey.kVK_ANSI_Equal.rawValue), combineFlag: combineFlag)
//            self.keyboardCombine(virtualKey: CGKeyCode(KeyVirtualKey.kVK_ANSI_Equal.rawValue), combineFlag: combineFlag, keyDown: false)


            //缩小 在safari 打开网页，测试正常
//            let combineFlag = CGEventFlags(rawValue: CGEventFlags.maskAlternate.rawValue | CGEventFlags.maskCommand.rawValue)
//            self.keyboardCombine(virtualKey: CGKeyCode(KeyVirtualKey.kVK_ANSI_Minus.rawValue), combineFlag: combineFlag)
//            self.keyboardCombine(virtualKey: CGKeyCode(KeyVirtualKey.kVK_ANSI_Minus.rawValue), combineFlag: combineFlag, keyDown: false)


            //系统控制键 control + 方向键， 采用模拟输入键 无效，需要调用 system event app
//            self.switch2RightDesktop()
//            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
//                self.switch2LeftDesktop()
//            }
            
            
            //mission control  control + 向上箭头，再次调用取消
//            self.toggleMissionControl()
            
            //打开 lauchpad，通过c语言通知的方式打开
//            openLauchpad()
//            DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
//                //再次调用表示关闭
//                openLauchpad()
//            }
            
            self.executeAppleScript(keyCode: 107)
        }
    }
    
    
    class func ctrlAndArrow()  {
        
            
        struct structControl{
            static var keyCode: Int16 = 0x7B
        }
        //快捷键用户可自行设置，所以需要能读取快捷键？
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {

            self.install()

            let str = String(structControl.keyCode)
//            self.exectueScript()
            
            self.exectueControlScript(str)
            structControl.keyCode += 1
        }
        
       
        
        //ctrl + 箭头没反应，不知道是否系统限制？ 应该可以通过 Applescript 来完成 ctrl + 箭头快捷键
                
//        let source = CGEventSource(stateID: CGEventSourceStateID.combinedSessionState)
//
//        if  let cmd_c_D = CGEvent(keyboardEventSource: source, virtualKey: CGKeyCode(KeyVirtualAssist.kVK_RightArrow.rawValue) , keyDown: true){
//            cmd_c_D.flags = .maskControl;
//
//            cmd_c_D.post(tap: .cghidEventTap)
//
//            print("command c")
//        }

        
        
        
        //各种F键无效 应该 system event 没有权限
//        let source = CGEventSource(stateID: CGEventSourceStateID.combinedSessionState)
//
//        if  let cmd_c_D = CGEvent(keyboardEventSource: source, virtualKey: CGKeyCode(KeyVirtualAssist.kVK_F3.rawValue) , keyDown: true){
//            cmd_c_D.flags = .maskCommand;
//
//            cmd_c_D.post(tap: .cghidEventTap)
//
//            print("command c")
//        }
        
    
        
    }
    
    
    /// 模拟键盘输入
    /// - Parameters:
    ///   - key: 虚拟键值
    ///   - keyDown: true->按下按键 false:松开按键
    class func keyboardInputKey(key: CGKeyCode, keyDown: Bool = true) {
        
        let source = CGEventSource(stateID: CGEventSourceStateID.hidSystemState)
        let event = CGEvent(keyboardEventSource: source, virtualKey: key, keyDown: keyDown)
        event?.post(tap: CGEventTapLocation.cghidEventTap)
        print("key \(key) is \(keyDown ? "down": "up")")
    }
   
    
    
    /// 组合按键
    /// - Parameters:
    ///   - virtualKey:  键的码值
    ///   - combineFlag: 组合键，如 command
    ///   - keyDown: true 表示键按下，false表示键up
    class func keyboardCombine(virtualKey: CGKeyCode, combineFlag: CGEventFlags, keyDown: Bool = true)  {
        
        
        if  let cmd_c_D = CGEvent(keyboardEventSource: nil, virtualKey: virtualKey, keyDown: keyDown){
            cmd_c_D.flags = combineFlag;
            cmd_c_D.post(tap:.cghidEventTap)
            print("command c")
        }
    }
    
    // MARK: ---- 通过字符串执行 applescript
    
    /*
      system event 需要通过applescript来执行，普通的模拟输入 按键 没有权限，执行看不到效果
     */
    
    class func switch2RightDesktop()  {
        
        self.executeAppleScriptWithControl(keyCode: UInt16(kVK_RightArrow))
    }
    
    class func switch2LeftDesktop()  {
        
        self.executeAppleScriptWithControl(keyCode: UInt16(kVK_LeftArrow))
    }
    
    class func toggleMissionControl()  {
        
        self.executeAppleScriptWithControl(keyCode: UInt16(kVK_UpArrow))
    }
    
    class func FunctionKeyTest() {
        
        self.executeAppleScript(keyCode: 103)
    }
    
    class func executeAppleScript(keyCode: UInt16)  {
        
        //从剪贴板复制内容
//        let scriptSource = "tell application \"System Events\"\rset KeyCode to (the clipboard as text)\r key code KeyCode using {control down}\r end tell"
        
//查看右边桌面
//        let scriptSource = "tell application \"System Events\"\r key code 124 using {control down}\r end tell"
        
        
        let scriptSource = "tell application \"System Events\"\r key code \(keyCode)"
        
        if let script = NSAppleScript(source: scriptSource){
            
             let eventDescriptor = script.executeAndReturnError(nil)
                
            print(eventDescriptor.stringValue ?? "")
            
        }
    }
    
    class func executeAppleScriptWithControl(keyCode: UInt16)  {
        
        //从剪贴板复制内容
//        let scriptSource = "tell application \"System Events\"\rset KeyCode to (the clipboard as text)\r key code KeyCode using {control down}\r end tell"
        
//查看右边桌面
//        let scriptSource = "tell application \"System Events\"\r key code 124 using {control down}\r end tell"
        
        
        let scriptSource = "tell application \"System Events\"\r key code \(keyCode) using {control down}\r end tell"
        
        if let script = NSAppleScript(source: scriptSource){
            
             let eventDescriptor = script.executeAndReturnError(nil)
                
            print(eventDescriptor.stringValue ?? "")
            
        }
    }
    
    
    // MARK: ----- 通过applescript文件来执行
    /*
     将利用系统提供的 AppleScript编辑器存储的 .scpt文件存储指定沙盒路径，然后执行的方式
     */
    class func check() -> Bool {
        
        let scriptName  = "control"

        let path = NSSearchPathForDirectoriesInDomains(.applicationScriptsDirectory, .userDomainMask, true)[0]
        let file = "\(path)/\(scriptName).scpt"
        return FileManager.default.fileExists(atPath: file)
    }
    
    class func install() {

        if !check() {

            let panel = NSSavePanel()
            panel.title = "保存AppleScript"
            panel.message = "请保存AppleScript文件至Application Scripts目录才可使用"
            //        panel.allowedFileTypes = ["json"]
            
            
            //必须最终保存的文件的名字
            let scriptName  = "control"
            panel.nameFieldStringValue = "\(scriptName).scpt"
            panel.directoryURL = FileManager.default.urls(for: .applicationScriptsDirectory, in: .userDomainMask)[0]
            panel.canCreateDirectories = false
            panel.delegate = nil

            if panel.runModal() == .OK {
                if let url = panel.url {
                    //  这里是你的项目的脚本的resource文件
                    if let resourceUrl = Bundle.main.url(forResource: scriptName, withExtension: "scpt") {
                        do {
                            let data = try Data(contentsOf: resourceUrl)
                            //测试换文件，没有权限，会写入失败
                            try data.write(to: url)
                            return

                        } catch {
                            panel.cancel(nil)
                            install()
                            return
                        }
                    }
                }
            }
            panel.cancel(nil)
            install()
        }
    }
    
    class func  exectueScript()  {
        
        
//        NSPasteboard.general.setString("124", forType: NSPasteboard.PasteboardType.string)
        
        let pboard = NSPasteboard.general
        pboard.declareTypes([.string], owner: nil)
        pboard.setString("124", forType: .string)
    
        
        var dict:NSDictionary?
                
        var dir = FileManager.default.urls(for: .applicationScriptsDirectory, in: .userDomainMask)[0]
        
        let scriptName  = "control"

        dir.appendPathComponent("\(scriptName).scpt")
                
        let script = NSAppleScript(contentsOf: dir, error: &dict)
        script?.executeAndReturnError(&dict)
                
        print(dict)
    }
    
    //applescript里面通过剪贴板动态获取内容，来执行
    class func  exectueControlScript(_ str: String)  {
        
        let pboard = NSPasteboard.general
        pboard.declareTypes([.string], owner: nil)
        pboard.setString(str, forType: .string)
    
        
        var dict:NSDictionary?
                
        var dir = FileManager.default.urls(for: .applicationScriptsDirectory, in: .userDomainMask)[0]
        
        let scriptName  = "control"

        dir.appendPathComponent("\(scriptName).scpt")
                
        let script = NSAppleScript(contentsOf: dir, error: &dict)
        script?.executeAndReturnError(&dict)
                
        print(dict)
    }
    
    

}

